
#include "ReqPipe.mqh"

#import "SocketPipeClientDLL.dll"
	int InitSocket();
 	int CloseSocket();
	int GetPacket(Handle &handle);
	int SendPacket(Handle handle);
    
    // For PacketReader
	int PacketReaderFree(Handle handle);
	int RequestGetLong(Handle handle, long &output);
	int RequestGetInt(Handle handle, int &output);
	int RequestGetDouble(Handle handle, double &output);
	int RequestGetString(Handle handle, char &pChar[], int length);
    
    // For PacketWriter
   #define PacketWriterHandle Handle
	Handle PacketWriterCreate();
	void PacketWriterFree(Handle handle);
	int PacketWriterSetInt(Handle handle, int data);
	int PacketWriterSetLong(Handle handle, long data);
	int PacketWriterSetDouble(Handle handle, double data);
	int PacketWriterSetString(Handle handle, char &pChar[]);

	// For PipeClinet
	PipeClientHandle PipeClientInit(char &ip[], int port);
	void PipeClientClose(PipeClientHandle handle);
	int PipeClientGetPacket(PipeClientHandle handle, PacketReaderHandle &pack);
	int PipeClientSendPacket(PipeClientHandle handle, PacketWriterHandle pack);


#import

enum RequestType
{
	RequestType_None = 0,
	RequestType_Test,
	RequestType_SendOrder,
	RequestType_SendOrder_Result,
	RequestType_RateByTime,
	RequestType_RateByTime_Result,
	RequestType_SymbolNameList,
	RequestType_SymbolNameList_Result,
	RequestType_RateByCount,
	RequestType_RateByCount_Result,
	RequestType_RateByTime2,
	RequestType_RateByTime2_Result,
	RequestType_SimpleTest,
	RequestType_GetAction,
	RequestType_GetAction_Result,
	RequestType_GetRateInfo,
	RequestType_GetRateInfo_Result,
	RequestType_SendRate,
	RequestType_SendRate_Result,
    RequestType_MAX,
};   

#define D_SYMBOL_NAME_MAX (24)
#define D_TIME_STRING_MAX (20)
#define D_STRING_LENGTH_MAX (1024 * 100)


ReqPipe::ReqPipe()
{
}

ReqPipe::~ReqPipe()
{
	PipeClientClose(m_pipeHandle);
}

void ReqPipe::Init(string ip, int port)
{
	char ipChar[16];
    StringToCharArray(ip, ipChar, 0, 16);

	m_ip = ip;
	m_port = port;
	m_pipeHandle = PipeClientInit(ipChar, port);

}

void ReqPipe::Close()
{
	PipeClientClose(m_pipeHandle);
}

Handle ReqPipe::SendReq(Handle pack)
{
	int ret;
	Handle res = NULL;
	ret = PipeClientSendPacket(m_pipeHandle, pack);
	ret = PipeClientGetPacket(m_pipeHandle, res);
	return res;
}

// ===================
// PacketWriter
// ====================
PacketWriter::PacketWriter()
{
	m_handle = NULL;
}
PacketWriter::~PacketWriter()
{

}
void PacketWriter::Open()
{
	m_handle = PacketWriterCreate();
}
void PacketWriter::Close()
{
	if(m_handle == NULL)
		return;

	PacketWriterFree(m_handle);
	m_handle = NULL;
}

void PacketWriter::SetInt(int value)
{
	PacketWriterSetInt(m_handle, value);
}
void PacketWriter::SetLong(long data)
{
	PacketWriterSetLong(m_handle, data);
}
void PacketWriter::SetDouble(double data)
{
	PacketWriterSetDouble(m_handle, data);
}
void PacketWriter::SetString(string str)
{
    char strArr[D_STRING_LENGTH_MAX];
    StringToCharArray(str, strArr, 0, D_STRING_LENGTH_MAX);
    // Set SymbolName
    PacketWriterSetString(m_handle, strArr); 

}
void PacketWriter::SetDatetime(datetime time)
{
    char timeArr[D_TIME_STRING_MAX];
    StringToCharArray(TimeToString(time), timeArr, 0);
    PacketWriterSetString(m_handle, timeArr);
}
void PacketWriter::SetRate(MqlRates &rates)
{
	 SetDatetime(rates.time);
    SetDouble(rates.open);
    SetDouble(rates.close);
    SetDouble(rates.high);
    SetDouble(rates.low);
    SetLong(rates.tick_volume);
    SetLong(rates.real_volume);
    SetInt(rates.spread);
}


// =====================
// PacketReader
// ====================
PacketReader::PacketReader() 
{
	m_handle = NULL;
}
PacketReader::~PacketReader() {}

void PacketReader::Open(Handle readerHandle)
{
	m_handle = readerHandle;
}
void PacketReader::Close()
{
	PacketReaderFree(m_handle);
	m_handle = NULL;
}

void PacketReader::GetInt(int &data)
{
	RequestGetInt(m_handle, data);
}
void PacketReader::GetLong(long &data)
{
	RequestGetLong(m_handle, data);
}
void PacketReader::GetDouble(double &data)
{
	RequestGetDouble(m_handle, data);
}
void PacketReader::GetString(string &str)
{
	char strArr[D_STRING_LENGTH_MAX];
    int ret = RequestGetString(m_handle, strArr, D_STRING_LENGTH_MAX);
    str = CharArrayToString(strArr, 0, D_STRING_LENGTH_MAX);
}
void PacketReader::GetDatetime(datetime &data)
{
    string str;
    GetString(str);
    data =  StringToTime(str);
}



// ================================
// ===================
// SimpleTestReq
// ====================
SimpleTestReq::SimpleTestReq()
{

}

SimpleTestReq::~SimpleTestReq()
{

}

int SimpleTestReq::Send()
{
	Handle writeHandle = PacketWriterCreate();
	PacketWriterSetInt(writeHandle, 0);	
	SendPacket(writeHandle);
	PacketWriterFree(writeHandle);
	
	return 0;

}



// ===================
// GetActionReq
// ====================
GetActionReq::GetActionReq()
{
}

GetActionReq::~GetActionReq()
{

}

GetActionReq::Init(ReqPipe &pipe)
{
	m_pipe = pipe;
}

bool GetActionReq::GetAction(MqlRates &rates[], int count)
{
   int type;
	OrderLength = count;

	PacketWriter writer;
	writer.Open();
	// Set type
	writer.SetInt(RequestType_GetAction);
	// Set data count
	writer.SetInt(count);
	// Set rate data
	for(int i=0;i<count;i++)
	{
		writer.SetRate(rates[i]);
	}

 	Handle readerHandle = m_pipe.SendReq(writer.m_handle);
 	PacketReader reader;
 	reader.Open(readerHandle);
 	reader.GetInt(type);
 	for(int j=0;j<count;j++)
 	{
 	   int orderType;
 		reader.GetInt(orderType);
 		OrderArr[j] = (OrderType)orderType;
 	}
    
    writer.Close();
    reader.Close();
    
    return true;
}


// ===================
// GetRateInfoReq
// ====================
GetRateInfoReq::GetRateInfoReq()
{
}

GetRateInfoReq::~GetRateInfoReq()
{

}

GetRateInfoReq::Init(ReqPipe &pipe)
{
	m_pipe = pipe;
}

bool GetRateInfoReq::GetRateInfo(void)
{
   int type;
	PacketWriter writer;
	writer.Open();
	// Set type
	writer.SetInt(RequestType_GetRateInfo);
	
 	Handle readerHandle = m_pipe.SendReq(writer.m_handle);
 	PacketReader reader;
 	reader.Open(readerHandle);
 	reader.GetInt(type);
 	
 	reader.GetString(SymbolName);
 	int timeFrame;
 	reader.GetInt(timeFrame);
 	switch(timeFrame)
 	{
 	   case 5:
 	      TimeFrame = PERIOD_M5;
 	      break;;
      case 30:
         TimeFrame = PERIOD_M30;
 	      break;
 	   default:
 	      printf("GetRateInfo: error! TimeFrame=%d", timeFrame);
 	      break;
 	}
 	reader.GetDatetime(StartTime);
 	reader.GetDatetime(EndTime);
    
    writer.Close();
    reader.Close();
    
    return true;
}


// ===================
// SendRateReq
// ====================
SendRateReq::SendRateReq()
{
}

SendRateReq::~SendRateReq()
{

}

SendRateReq::Init(ReqPipe &pipe)
{
	m_pipe = pipe;
}

bool SendRateReq::SendRate(MqlRates &rates[], int offset, int count)
{
   int type;

	PacketWriter writer;
	writer.Open();
	// Set type
	writer.SetInt(RequestType_SendRate);
	writer.SetInt(count);
	for(int i=0;i<count;i++)
	{
	   writer.SetRate(rates[offset+i]);
	}
	
 	Handle readerHandle = m_pipe.SendReq(writer.m_handle);
 	PacketReader reader;
 	reader.Open(readerHandle);
 	reader.GetInt(type);
 	
    writer.Close();
    reader.Close();
    
    return true;
}

